#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#include "rfs-client.h"
int numread;

int enviar(PACKAGE *package, int fd) {
    write(fd, package, sizeof (PACKAGE));
}

int recibir(PACKAGE * package, int fd) {
    read(fd, package, sizeof (PACKAGE));
}

int
rls(PACKAGE *package) {

    // envío el comando
    package->op = RLS;
    enviar(package, package->to);

    // creo el buffer para el resultado
    char rdbuf[DATA_LENGTH];
    memset(rdbuf, '\0', DATA_LENGTH);

    // creo el puntero que va a contener el resultado final
    char * output = (char *) malloc(1);
    output[0] = '\0';

    do {
        // recibo el paquete
        recibir(package, package->from);
        // agrego memoria para alojar el resultado
        output = (char *) realloc(output, strlen(output) + strlen(package->data));
        // agrego la cadena que viene con el paquete
        strcat(output, package->data);
    } while (package->offset == DATA_LENGTH);

    // imprimo resultado
    printf("Resultado\n");
    printf("-----------------\n");
    printf("%s\n", output);
    printf("-----------------\n");
    
    // retorno cantidad de paquetes leídos
    return package->block_count;
}

int
rcd(PACKAGE *package) {

    // envío el comando
    package->op = RCD;
    enviar(package, package->to);

    // creo el buffer para el resultado
    char rdbuf[DATA_LENGTH];
    memset(rdbuf, '\0', DATA_LENGTH);

    // creo el puntero que va a contener el resultado final
    char * output = (char *) malloc(1);
    output[0] = '\0';

    do {
        // recibo el paquete
        recibir(package, package->from);
        // agrego memoria para alojar el resultado
        output = realloc(output, strlen(output) + strlen(package->data));
        // agrego la cadena que viene con el paquete
        strcat(output, package->data);
    } while (package->offset == DATA_LENGTH);

    // imprimo resultado
    printf("Resultado\n");
    printf("-----------------\n");
    printf("%s\n", output);
    printf("-----------------\n");

    // retorno cantidad de paquetes leídos
    return package->block_count;
}

int
get(PACKAGE *package) {

    FILE * file = NULL;

    char * file_name = (char *) malloc(DATA_LENGTH);
    strncpy(file_name, package->data, DATA_LENGTH);
    package->block_count = 0;
    do {
        package->op = GET;
        strncpy(package->data, file_name, DATA_LENGTH);
        enviar(package, package->to);
        recibir(package, package->from);
        if (package->op != ERROR) {
            if (file == NULL) {
                file = fopen(file_name, "w");
            }
            // escribo el bloque del lado del cliente
            fwrite(package->data, sizeof (char), package->offset, file);
            // preparo la llamada siguiente
            package->block_count++;
            // traigo el siguiente bloque            
        } else {
            continue;
        }
    } while (package->offset == DATA_LENGTH);
    if (file != NULL)
        // cierro el archivo
        fclose(file);
    printf("-----------------\n");
    if (package->op != ERROR) {
        int i = package->block_count;
        i--;
        i *= DATA_LENGTH;
        i += package->offset;
        printf("Resultado:\nSe descargó correctamente el archivo '%s'.\n"
                "Se transmitieron %i bytes en total.\n",
                file_name, i);
    } else {
        printf("Ocurrió un error al intentar descargar el archivo.\n"
                "El archivo '%s' no existe o el servidor no tiene permiso para leerlo.\n",
                file_name);
    }
    printf("-----------------\n");

    free(file_name);
    return package->op;
}

int
put(PACKAGE *package) {
    FILE * file = NULL;

    char * file_name = (char *) malloc(DATA_LENGTH);
    strncpy(file_name, package->data, DATA_LENGTH);
    package->block_count = 0;
    do {
        package->op = PUT;
        strncpy(package->data, file_name, DATA_LENGTH);
        //envío comando y nombre de archivo
        enviar(package, package->to);
        // recibo confirmación
        recibir(package, package->from);
        // si no hubo error al crear el archivo en el servidor
        if (package->op != ERROR) {
            // ...lo abro en el cliente
            if (file == NULL) {
                file = fopen(file_name, "r");
            }
            // leo el bloque
            package->offset = fread(package->data, sizeof (char), DATA_LENGTH, file);
            // envio el bloque
            enviar(package, package->to);
            // preparo la llamada siguiente
            package->block_count++;
        } else {
            continue;
        }
        // hasta que haya leído y enviado una porción menor al tamaño máximo (señal del fin de archivo)
    } while (package->offset == DATA_LENGTH);
    if (file != NULL)
        // cierro el archivo
        fclose(file);
    printf("-----------------\n");
    if (package->op != ERROR) {
        int i = package->block_count;
        i--;
        i *= DATA_LENGTH;
        i += package->offset;
        printf("Resultado:\nSe subió correctamente el archivo '%s'.\n"
                "Se transmitieron %i bytes en total.\n",
                file_name, i);
    } else {
        printf("Ocurrió un error al intentar subir el archivo.\n"
                "El archivo '%s' no existe o no se tiene permiso para leerlo.\n",
                file_name);
    }
    printf("-----------------\n");

    free(file_name);
    return package->op;
}

